package com.ljx.IteratorMode;

import lombok.Data;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

/**
 *
 * 迭代器模式
 *
 * 定义：
 * 提供一个对象来顺序访问聚合对象中的一系列数据，而不暴露聚合对象的内部表示
 *
 * 优点：**
 * 它支持以不同的方式遍历一个聚合对象，在同一个聚合对象上可以定义多种遍历方式。
 * 在迭代器模式中只需要用一个不同的迭代器来替换原有迭代器即可改变遍历算法，
 * 我们也可以自己定义迭代器的子类以支持新的遍历方式。
 * 迭代器简化了聚合类。由于引入了迭代器，在原有的聚合对象中不需要再自行提供数据遍历等方法，这样可以简化聚合类的设计。
 * 在迭代器模式中，由于引入了抽象层，增加新的聚合类和迭代器类都很方便，无须修改原有代码，满足 “开闭原则” 的要求。
 *
 * 缺点：**
 * 增加了类的个数，这在一定程度上增加了系统的复杂性
 *
 * 使用场景：
 * 当需要为聚合对象提供多种遍历方式时。
 * 当需要为遍历不同的聚合结构提供一个统一的接口时。
 * 当访问一个聚合对象的内容而无须暴露其内部细节的表示时
 *
 * 经典案例：
 * JDK Iterator接口
 *
 * @作者 LJX
 * @日期 2022/12/26 15:31
 */
public class IteratorTest {

    public static void main(String[] args) {

        //创建聚合对象
        ObjectContainer<Goods> goodsObjectContainer = new ObjectContainerImpl<Goods>();
        goodsObjectContainer.addObj(new Goods("电脑", new BigDecimal(999999)));
        goodsObjectContainer.addObj(new Goods("电视", new BigDecimal("999.99")));
        goodsObjectContainer.addObj(new Goods("冰箱", new BigDecimal("555.78")));
        goodsObjectContainer.addObj(new Goods("空调", new BigDecimal("888.6")));
        goodsObjectContainer.addObj(new Goods("手机", new BigDecimal(999)));

        ObjectIterator<Goods> objIterator = goodsObjectContainer.getObjIterator();
        while (objIterator.hasNext()){
            Goods next = objIterator.next();
            System.out.println(next.toString());
        }
    }

}

/**
 * 抽象迭代器
 * @param <T>
 */
interface ObjectIterator<T> {

    /**
     * 是否有下一个
     * @return
     */
    Boolean hasNext();

    /**
     * 获取下一个
     * @return
     */
    T next();

}

/**
 * 具体迭代器
 * @param <T>
 */
class ObjectIteratorImpl<T> implements ObjectIterator<T>{

    private final List<T> list;
    private Integer index = 0;

    public ObjectIteratorImpl(List<T> list) {
        this.list = list;
    }

    @Override
    public Boolean hasNext() {
        return index < list.size();
    }

    @Override
    public T next() {
        T t = list.get(index);
        index++;
        return t;
    }
}

/**
 * 抽象容器
 * @param <T>
 */
interface ObjectContainer<T> {
    /**
     * 添加对象
     * @param t
     */
    void addObj(T t);

    /**
     * 删除对象
     * @param t
     */
    void removeObj(T t);

    /**
     * 获取迭代器
     * @param c
     * @return
     */
    ObjectIterator<T> getObjIterator();

}

/**
 * 具体容器
 */
class ObjectContainerImpl<T> implements ObjectContainer<T>{

    private final List<T> list = new ArrayList<T>(); //容器列表

    @Override
    public void addObj(T t) {
        list.add(t);
    }

    @Override
    public void removeObj(T t) {
        list.remove(t);
    }

    @Override
    public ObjectIterator<T> getObjIterator() {
        return new ObjectIteratorImpl<T>(list);
    }
}

/**
 * 商品类
 */
@Data
class Goods{

    String name;

    BigDecimal price;

    public Goods(String name, BigDecimal price) {
        this.name = name;
        this.price = price;
    }

    @Override
    public String toString() {
        return "Goods{" +
                "name='" + name + '\'' +
                ", price=" + price.toPlainString() +
                '}';
    }
}